﻿/* Muaz Khan – http://dashingquill.web.officelive.com */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DTweet.Models;

namespace DTweet.Helpers
{
    public static class CirclesRelatedExtensions
    {
        /***********************************
         * Create new circle
         ***********************************/
        public static void CreateCircle(this DatabaseEntities db, string circleName, string userToFollow)
        {
            ErrorsHelper.IsError = false;

            var sameCircle = db.Circles.Where(c => c.Name == circleName && c.UserToken == Static.CurrentUser.UniqueToken).FirstOrDefault() != null;
            if (sameCircle)
            {
                var message = "Duplicate names are not allowed for circles.";
                message.AlertForError();
                return;
            }

            try
            {
                var circle = new Circle
                {
                    Name = circleName,
                    CreationDate = DateTime.Now,
                    UserToken = Static.CurrentUser.UniqueToken,
                    Token = UniqueTokenForCircle(db),
                    Members = userToFollow,
                    MembersCount = 1
                };                
                db.Circles.AddObject(circle);
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }

        /***********************************
         * Validate if unique-token already taken for any circle
         ***********************************/
        static string UniqueTokenForCircle(DatabaseEntities db)
        {
        Back:
            var randomNumber = RandomNumbers.GetRandomNumbers();
            var circle = db.Circles.Where(a => a.Token == randomNumber).FirstOrDefault();
            if (circle != null) goto Back;

            return randomNumber;
        }

        /***********************************
         * Circle or Uncircle the user
         ***********************************/
        public static void InOrOutFromCircle(this DatabaseEntities db, string circleName, string userToken)
        {
            ErrorsHelper.IsError = false;
            ResultHelper.InCircle = false;
            ResultHelper.FoundInAnyCircle = false;

            try
            {
                var currentUserToken = Static.CurrentUser.UniqueToken;
                var circle = db.Circles.Where(c => c.Name == circleName && c.UserToken == currentUserToken).FirstOrDefault();
                if (circleName == null) throw new Exception("Circle \"" + circleName + "\" not found!");

                if (circle.MembersCount > 0 && circle.Members.Contains(userToken))
                {
                    if (!circle.Members.StartsWith(userToken)) circle.Members = circle.Members.Replace("," + userToken, "");
                    else circle.Members = circle.Members.Replace(userToken, "");
                    circle.MembersCount--;
                    ResultHelper.InCircle = false;
                }
                else
                {
                    if (circle.MembersCount > 0) circle.Members += "," + userToken;
                    else circle.Members = userToken;
                    circle.MembersCount++;
                    ResultHelper.InCircle = true;
                }
                db.SaveChanges();

                ResultHelper.FoundInAnyCircle = db.Circles.Where(c => c.UserToken == currentUserToken && c.MembersCount > 0 && c.Members.Contains(userToken)).FirstOrDefault() != null;
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }

        /***********************************
         * Validate whether it is circle-name or user-name
         ***********************************/
        public static void ValidatecircleOrUser(this DatabaseEntities db, string input)
        {
            try
            {
                var circle = db.Circles.Where(c => c.Name == input).FirstOrDefault();
                if (circle != null)
                {
                    ResultHelper.IsCircle = true;
                    ResultHelper.CircleName = circle.Name;
                    ResultHelper.CircleToken = circle.Token;
                }
                else
                {
                    var user = db.Accounts.Where(a => a.UserName == input || a.FullName == input).FirstOrDefault();
                    if (user != null)
                    {
                        var currentUser = Static.CurrentUser;
                        if (user.UniqueToken != currentUser.UniqueToken)
                        {
                            ResultHelper.IsUser = true;
                            ResultHelper.UserToken = user.UniqueToken;
                            ResultHelper.UserFullName = user.FullName;
                        }
                    }
                    else ResultHelper.IsUser = false;
                    ResultHelper.IsCircle = false;
                }
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }

        /***********************************
         * Getting members names from a circle
         ***********************************/
        public static string GetCircleMembersNames(this DatabaseEntities db, string circleMembers)
        {
            var split = circleMembers.Split(',').Distinct();
            var result = "";
            foreach (var user in split)
            {
                var u = user.GetAccountByUserToken(db);
                if (u != null) result += u.FullName + ", ";
            }
            if (result.Contains(",")) result = result.Substring(0, result.Length - 2);
            if (result.Length > 60) result = result.Substring(0, 60) + "...";
            return result;
        }

        /***********************************
         * UnCircling a user - i.e. removing from the circle
         ***********************************/
        public static void RemoveUserFromCircle(this DatabaseEntities db, string circleToken, string userToken)
        {
            ErrorsHelper.IsError = false;
            ResultHelper.UserFullName = null;

            /* Validating userToken */
            var user = db.Accounts.Where(a => a.UniqueToken == userToken).FirstOrDefault();
            if (user == null)
            {
                var errorMessage = "Invalid user token detected. Please refresh the page and try again.";
                errorMessage.AlertForError();
                return;
            }
            ResultHelper.UserFullName = user.FullName;

            /* Validating circleToken */
            var circle = db.Circles.Where(c => c.Token == circleToken && c.UserToken == Static.CurrentUser.UniqueToken).FirstOrDefault();
            if (circle == null || circle.MembersCount <= 0)
            {
                var errorMessage = "";
                errorMessage.AlertForError();
                return;
            }

            try
            {
                if (circle.Members.Contains(userToken)) circle.MembersCount--;

                if (circle.Members.Contains(userToken + ","))
                {
                    circle.Members = circle.Members.Replace(userToken + ",", "");
                }
                else if (circle.Members.Contains("," + userToken))
                {
                    circle.Members = circle.Members.Replace("," + userToken, "");
                }
                else if (circle.Members.Contains(userToken))
                {
                    circle.Members = circle.Members.Replace(userToken, "");
                }
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }

        /***********************************
         * Deleting the circle
         ***********************************/
        public static void DeleteCircle(this DatabaseEntities db, string circleToken)
        {
            ErrorsHelper.IsError = false;
            try
            {
                var circle = db.Circles.Where(c => c.Token == circleToken && c.UserToken == Static.CurrentUser.UniqueToken).FirstOrDefault();
                if (circle == null) throw new Exception("Circle not exists! -- or -- you are not the owner of this circle!!");

                db.DeleteObject(circle);
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }

        /***********************************
         * "Circles" page - Click on the circle name to get members - tokens help us remove that user from the circle (on user action!)
         ***********************************/
        public static CircleMembers GetMembersFromCircle(this DatabaseEntities db, string circleToken)
        {
            ErrorsHelper.IsError = false;
            try
            {
                var circle = db.Circles.Where(c => c.Token == circleToken).FirstOrDefault();
                if (circle == null) throw new Exception("Circle not found!");

                if (circle.MembersCount <= 0)
                {
                    return new CircleMembers { Members = "No members yet!" };
                }

                var members = "";
                foreach (var m in circle.Members.Split(','))
                {
                    var user = m.GetAccountByUserToken(db);
                    if (user != null)
                    {
                        members += user.FullName + ",";
                    }
                }
                members = members.Substring(0, members.Length - 1);
                var membersTokens = circle.Members;

                return new CircleMembers { Members = members, Tokens = membersTokens };
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
            return null;
        }

        /***********************************
         * Updating Circle Name
         ***********************************/
        public static void UpdateCircleName(this DatabaseEntities db, string circleName, string circleToken)
        {
            ErrorsHelper.IsError = false;
            try
            {
                var circle = db.Circles.Where(c => c.Token == circleToken).FirstOrDefault();

                if (circle == null) throw new Exception("Circle not found!");

                if (circle.UserToken != Static.CurrentUser.UniqueToken)
                    throw new Exception("You are not the owner of this circle!");

                circle.Name = circleName;
                db.SaveChanges();
            }
            catch (Exception ex)
            {
                ex.Message.AlertForError();
            }
        }
    }
}